/**
 * @file ctrl.c
 * @brief 遥控器控制模块实现文件
 *        包含DT7/VT13遥控器初始化、数据解算、串口中断处理等功能，支持遥控器（RC）和键鼠（KM）两种控制模式
 * @author WeiFan Qiu (qiuweifan0523@faxmail.com)
 * @version 1.0
 * @date 2025-08-08
 * 
 * @copyright Copyright (c) 2025 邱伟凡
 * 
 * @par 修改日志:
 * - 2025-08-08: 初始版本创建，实现DT7/VT13遥控器基础控制逻辑
 * - 2025-08-29: 修改部分名字
 * 
 * @bug 待解决问题:
 * - 未使用QWF_Usart里的双缓冲相关函数
 */
#include "ctrl.h"
#include "QWF_Usart.h"

// 外部声明控制功能函数（具体实现由其他模块提供）
extern void QWF_Ctrl_Func(void);
#define DT7_hsuart	huart5
#define DT7_hdma	hdma_uart5_rx
#define VT13_hsuart	huart1
#define VT13_hdma	hdma_usart1_rx
/**
 * @def error_ch0~error_ch3
 * @brief 遥控器通道0~3的校准偏移量（当前硬编码为0，需根据实际硬件校准）
 */
#define error_ch0					(0)
#define error_ch1					(0)
#define error_ch2					(0)
#define error_ch3					(0)

/**
 * @def RC_FRAME_LENGTH
 * @brief DT7遥控器串口数据帧长度（18字节，双缓冲故乘2）
 */
#define RC_FRAME_LENGTH 			(18u)

/***********************************示意图******************************************
						|						s:上1中3下2
						|						ch0/2:右+1684左-364	
						|						ch1/3:上+1684下-364	
						|
		-----------------------------------	s2:底盘模式;s1:云台模式
		|（S1）						(S2)   |s2_mode1:正常模式;s2_mode3:底盘跟随;s2_mode2:小陀螺;
		|	  +ch3				+ch1       |s1_mode1:控制在目前角度不动;s1_mode2:云台移动;s1_mode3:视觉跟随;		
		|	    |				  |	       |左:↑前↓后←左→右
		|-ch2--左--+ch2		-ch0--右--+ch0 |右:↑pitch抬头↓pitch低头←yaw左转→yaw右转	
		|	    |				  |        |	or←左转→右转
		|	  -ch3				-ch1       |
		------------------------------------
************************************************************************************/
static DT7_Ctrl_t DT7_CtrlData[2];
// VT13遥控器数据存储结构体（双缓冲）
static VT13_Ctrl_t VT13_CtrlData[2];
// 裁判系统控制数据存储结构体（双缓冲）
static remote_control_t Judge_CtrlData[2];

// 全局控制变量初始化（默认使用DT7遥控器，RC控制模式）
static Ctrl_t Ctrl={.type=DT7,.mode=RC,.Judge={Judge_CtrlData,Judge_CtrlData+1},.DT7={DT7_CtrlData,DT7_CtrlData+1},.VT13={VT13_CtrlData,VT13_CtrlData+1}};
Ctrl_t* ctrl=&Ctrl;

#if Circuit_Boards!=Chassis_Circuit_Boards//非底盘
#include "head.h"
#include "communicate.h"
#include "state.h"
#include "QWF_Math.h"

/***********************************DT7遥控器驱动*************************************/
extern UART_HandleTypeDef DT7_hsuart;
extern DMA_HandleTypeDef DT7_hdma;

// DT7遥控器串口接收双缓冲（每缓冲区18字节）
static uint8_t dt7_rx_buf[2][RC_FRAME_LENGTH]; 
/**
 * @brief DT7遥控器串口+DMA初始化（双缓冲模式）
 * @details 配置串口空闲中断和DMA双缓冲接收，实现无丢失数据采集
 * @note 依赖huart2和hdma_usart2_rx硬件句柄
 */
void DT7_Init(void){
QWF_double_buffer_dma_idle_Init(&DT7_hsuart,&DT7_hdma,dt7_rx_buf[0],dt7_rx_buf[1],RC_FRAME_LENGTH);
}

/**
 * @brief DT7遥控器数据解算函数
 * @param pData 指向串口接收数据的指针（18字节）
 * @details 解析摇杆、开关、鼠标键盘数据，处理死区并通过通信结构体转发
 * @note 支持RC（遥控器）和KM（键鼠）两种控制模式自动切换
 */
static void DT7_rx_func(uint8_t *pData){
	if(pData == NULL) return;
	qwf_state->head.rc.dt7.online.tick=qwf_state->sys_tick;  // 更新遥控器在线计时（防丢失）
	if(ctrl->type!=DT7) return;  // 非DT7类型时跳过解算
	// 检测是否为键鼠模式（键鼠数据区非零）
	for(int i=6;i<=15;i++){
		if(pData[i]){ 
			ctrl->mode=KM;
			break; 
		}
	}
	if (ctrl->mode==RC){
		// 解析遥控器摇杆通道值（ch0~ch3）
		DT7_CtrlData[now].rc.ch[0] = (int16_t)((((int16_t)pData[0] | ((int16_t)pData[1]<<8)) & 0x07FF) - error_ch0 - 1024);
		DT7_CtrlData[now].rc.ch[1] = (int16_t)((((int16_t)pData[1]>>3 | ((int16_t)pData[2]<<5)) & 0x07FF) - error_ch1 - 1024);
		DT7_CtrlData[now].rc.ch[2] = (int16_t)((((int16_t)pData[2]>>6 | ((int16_t)pData[3]<<2) | ((int16_t)pData[4]<<10)) & 0x07FF) - error_ch2 - 1024);
		DT7_CtrlData[now].rc.ch[3] = (int16_t)((((int16_t)pData[4]>>1 | ((int16_t)pData[5]<<7)) & 0x07FF) - error_ch3 - 1024);

		// 应用死区处理（消除摇杆中立区误差）
		DT7_CtrlData[now].rc.ch[0] = QWF_Dead(DT7_CtrlData[now].rc.ch[0], 10, -10);
		DT7_CtrlData[now].rc.ch[1] = QWF_Dead(DT7_CtrlData[now].rc.ch[1], 10, -10);
		DT7_CtrlData[now].rc.ch[2] = QWF_Dead(DT7_CtrlData[now].rc.ch[2], 10, -10);
		DT7_CtrlData[now].rc.ch[3] = QWF_Dead(DT7_CtrlData[now].rc.ch[3], 10, -10);

		// 解析开关状态和旋钮值
		DT7_CtrlData[now].rc.s[0]   = (((pData[5]) >> 4) & 0x000C) >> 2;
		DT7_CtrlData[now].rc.s[1]   = (((pData[5]) >> 4) & 0x0003);
		DT7_CtrlData[now].rc.knob   = ((uint16_t)pData[16]) | ((uint16_t)pData[17]<<8) - 1024;
	}
	else if (ctrl->mode==KM){
		// 解析鼠标坐标和按键数据
		DT7_CtrlData[now].mouse.x     = ((int16_t)pData[6]) | ((int16_t)pData[7]<<8);
		DT7_CtrlData[now].mouse.y     = ((int16_t)pData[8]) | ((int16_t)pData[9]<<8);
		DT7_CtrlData[now].mouse.z     = ((int16_t)pData[10]) | ((int16_t)pData[11]<<8);
		DT7_CtrlData[now].mouse.press_l = pData[12];
		DT7_CtrlData[now].mouse.press_r = pData[13];
		*(int16_t*)(&DT7_CtrlData[now].key) = ((int16_t)pData[14]) | ((int16_t)pData[15]<<8);
	}

	#if Circuit_Boards==Head_Circuit_Boards
	
	if (ctrl->mode==RC){
		for(int i=0;i<6;i++) communicate->head.ctrl.befor.data.buffer[i] = pData[0+i];
		communicate->head.ctrl.befor.data.buffer[6] = pData[16];
		communicate->head.ctrl.later.data.buffer[0] = pData[17];
	}
	else if(ctrl->mode==KM){
		for(int i=0;i<7;i++) communicate->head.ctrl.befor.data.buffer[i] = pData[6+i];
		for(int i=0;i<=2;i++) communicate->head.ctrl.later.data.buffer[i] = pData[13+i];
	}
	#endif

	QWF_Ctrl_Func();  // 触发控制功能回调
}

/**
 * @brief DT7遥控器串口空闲中断回调函数
 * @details 处理DMA双缓冲切换，检查数据完整性后调用解算函数
 * @note 依赖huart2串口和hdma_usart2_rx DMA句柄
 */
void DT7_Callback(void){
	QWF_double_buffer_dma_idle_callback(&DT7_hsuart,&DT7_hdma,RC_FRAME_LENGTH,DT7_rx_func);
}

/***********************************VT13遥控器驱动*************************************/
#include "Judge.h"
#define VT13_FRAME_LENGTH 			(21u)
extern UART_HandleTypeDef huart1;
extern DMA_HandleTypeDef hdma_usart1_rx;

// VT13遥控器串口接收双缓冲（每缓冲区21字节）
static uint8_t vt13_rx_buf[2][VT13_FRAME_LENGTH]; 
DMA_Stream_TypeDef *VT13_DMA_DBuf;

/**
 * @brief VT13遥控器串口+DMA初始化（双缓冲模式）
 * @details 配置逻辑与DT7类似，数据帧长度为21字节
 */
void VT13_Init(void){
	QWF_double_buffer_dma_idle_Init(&VT13_hsuart,&VT13_hdma,vt13_rx_buf[0],vt13_rx_buf[1],VT13_FRAME_LENGTH);
}

/**
 * @brief VT13遥控器数据处理函数
 * @param pData 指向串口接收数据的指针（21字节）
 * @details 解析遥控器摇杆、开关、鼠标键盘数据，支持RC（遥控器）和KM（键鼠）模式切换
 * @note 保留原始未启用的CRC校验代码（用于数据完整性验证）
 */
static void VT13_DataProcess(uint8_t *pData){
	if(pData == NULL) return;
	if(pData[0] == 0xA9 && pData[1] == 0x53) {  // 验证VT13数据帧头
//		VT13_CtrlData[now].crc16 = (pData[19] | (pData[20] << 8));  // 未启用的CRC校验（保留原始注释）
		if(Verify_CRC16_Check_Sum(pData,21)){  // CRC校验通过（实际未启用）
			qwf_state->head.rc.vt13.online.tick=qwf_state->sys_tick;  // 更新遥控器在线计时
			if(ctrl->type!=VT13) return;  // 非VT13类型时跳过解算

			// 检测是否为键鼠模式（键鼠数据区非零）
			for(int i=10;i<=18;i++){
				if(pData[i]){//有键鼠数据就是键鼠
					if(ctrl->mode==RC){
						gimbal_mode[now]=gimbal_normal;
					}
					ctrl->mode=KM;
					break;
				}
			}
			// 根据控制模式分支处理
			switch((int)ctrl->mode){
				case (RC):{
					// 解析遥控器摇杆通道值（ch0~ch3）、开关及旋钮数据
					VT13_CtrlData[now].rc.ch[0] = (pData[2] | (pData[3] << 8)) & 0x07ff;        // 通道0原始值
					VT13_CtrlData[now].rc.ch[1] = ((pData[3] >> 3) | (pData[4] << 5)) & 0x07ff; // 通道1原始值
					VT13_CtrlData[now].rc.ch[2] = ((pData[4] >> 6) | (pData[5] << 2) | (pData[6] << 10)) & 0x07ff; // 通道2原始值
					VT13_CtrlData[now].rc.ch[3] = ((pData[6] >> 1) | (pData[7] << 7)) & 0x07ff; // 通道3原始值
					VT13_CtrlData[now].rc.mode_sw = ((pData[7] >> 4) & 0x0003);  // 模式开关状态
					VT13_CtrlData[now].rc.stop = ((pData[7] >> 6) & 0x01);       // 停止按钮状态
					VT13_CtrlData[now].rc.left_button = ((pData[7] >> 7) & 0x01); // 左功能键状态
					VT13_CtrlData[now].rc.right_button = ((pData[8] >> 0) & 0x01); // 右功能键状态
					VT13_CtrlData[now].rc.wheel = ((pData[8] >> 1) | (pData[9] << 7)) & 0x07FF; // 滚轮值
					VT13_CtrlData[now].rc.shutter = (pData[9] >> 4) & 0x01;       // 扳机按钮状态

					// 校准偏移（减去中间值1024）
					VT13_CtrlData[now].rc.ch[0] -= 1024;
					VT13_CtrlData[now].rc.ch[1] -= 1024;
					VT13_CtrlData[now].rc.ch[2] -= 1024;
					VT13_CtrlData[now].rc.ch[3] -= 1024;
					VT13_CtrlData[now].rc.wheel -= 1024;

					#if Circuit_Boards==Head_Circuit_Boards
					// 头电路板时通过通信结构体转发数据
					for(int i=0;i<7;i++) communicate->head.ctrl.befor.data.buffer[i] = pData[2+i];
					communicate->head.ctrl.later.data.buffer[0] = pData[9];
					#endif
				}break;

				case(KM):{
					// 解析鼠标坐标和按键数据
					VT13_CtrlData[now].mouse.x = (pData[10] | (pData[11] << 8));  // 鼠标X坐标
					VT13_CtrlData[now].mouse.y = (pData[12] | (pData[13] << 8));  // 鼠标Y坐标
					VT13_CtrlData[now].mouse.z = (pData[14] | (pData[15] << 8));  // 鼠标Z坐标（滚轮）
					VT13_CtrlData[now].mouse.press_l = (pData[16] >> 0) & 0x03;   // 左键状态
					VT13_CtrlData[now].mouse.press_r = (pData[16] >> 2) & 0x03;   // 右键状态
					VT13_CtrlData[now].mouse.middle  = (pData[16] >> 4) & 0x03;   // 中键状态
					*(int16_t*)(&VT13_CtrlData[now].key) = (pData[17] | (pData[18] << 8));  // 键盘按键

					#if Circuit_Boards==Head_Circuit_Boards
					// 头电路板时通过通信结构体转发数据
					for(int i=0;i<7;i++) communicate->head.ctrl.befor.data.buffer[i] = pData[10+i];
					for(int i=0;i<2;i++) communicate->head.ctrl.later.data.buffer[i] = pData[17+i];
					#endif
				}break;
			}
			QWF_Ctrl_Func();  // 触发控制功能回调
		}
	}
}

/**
 * @brief VT13遥控器串口空闲中断回调函数
 * @details 处理DMA双缓冲切换，检查数据完整性后调用数据处理函数
 * @note 依赖huart1串口和hdma_usart1_rx DMA句柄
 */
void VT13_Callback(void){
	QWF_double_buffer_dma_idle_callback(&VT13_hsuart,&VT13_hdma,VT13_FRAME_LENGTH,VT13_DataProcess);
}

/***********************************底盘模式控制处理*************************************/
#else	// 底盘
#include "communicate.h"
#include "QWF_Math.h"

/**
 * @brief 底盘控制数据接收回调函数
 * @details 底盘模式下，解析来自云台板的通信数据，更新DT7/VT13遥控器控制参数
 *          支持RC（遥控器）模式，根据遥控器类型（DT7/VT13）分支处理
 * @note 依赖communicate通信结构体同步数据
 */
void Ctrl_rx_func_chassis(void){
	// 根据当前控制模式分支处理（仅支持RC模式）	
	switch((int)ctrl->mode){
		case(RC):{
			// 根据遥控器类型（DT7/VT13）分支处理
			switch((int)ctrl->type){
				case VT13:{
					// 保存上一周期VT13数据（用于数据平滑处理）
					VT13_CtrlData[last]=VT13_CtrlData[now];
					// 从通信结构体解析VT13遥控器通道数据（来自云台板转发）
					VT13_CtrlData[now].rc.ch[0] = (communicate->head.ctrl.befor.data.buffer[2-2] | (communicate->head.ctrl.befor.data.buffer[3-2] << 8)) & 0x07ff;        // 通道0原始值
					VT13_CtrlData[now].rc.ch[1] = ((communicate->head.ctrl.befor.data.buffer[3-2] >> 3) | (communicate->head.ctrl.befor.data.buffer[4-2] << 5)) & 0x07ff; // 通道1原始值
					VT13_CtrlData[now].rc.ch[2] = ((communicate->head.ctrl.befor.data.buffer[4-2] >> 6) | (communicate->head.ctrl.befor.data.buffer[5-2] << 2) |          // 通道2原始值
												(communicate->head.ctrl.befor.data.buffer[6-2] << 10)) & 0x07ff;
					VT13_CtrlData[now].rc.ch[3] = ((communicate->head.ctrl.befor.data.buffer[6-2] >> 1) | (communicate->head.ctrl.befor.data.buffer[7-2] << 7)) & 0x07ff; // 通道3原始值
					// 解析开关状态和功能按键
					VT13_CtrlData[now].rc.mode_sw = ((communicate->head.ctrl.befor.data.buffer[7-2] >> 4) & 0x0003);  
					VT13_CtrlData[now].rc.stop = ((communicate->head.ctrl.befor.data.buffer[7-2] >> 6) & 0x01);       
					VT13_CtrlData[now].rc.left_button = ((communicate->head.ctrl.befor.data.buffer[7-2] >> 7) & 0x01);  
					VT13_CtrlData[now].rc.right_button = ((communicate->head.ctrl.befor.data.buffer[8-2] >> 0) & 0x01);  
					VT13_CtrlData[now].rc.wheel = ((communicate->head.ctrl.befor.data.buffer[8-2] >> 1) | (communicate->head.ctrl.later.data.buffer[9-9] << 7)) & 0x07FF;  // 滚轮值
					VT13_CtrlData[now].rc.shutter = (communicate->head.ctrl.later.data.buffer[9-9] >> 4) & 0x01;  
					// 校准偏移（转换为以0为中心的数值）
					VT13_CtrlData[now].rc.ch[0] -= 1024;
					VT13_CtrlData[now].rc.ch[1] -= 1024;
					VT13_CtrlData[now].rc.ch[2] -= 1024;
					VT13_CtrlData[now].rc.ch[3] -= 1024;
					VT13_CtrlData[now].rc.wheel -= 1024;
				}break;
				case(DT7):{
					// 保存上一周期DT7数据
					DT7_CtrlData[last]=DT7_CtrlData[now];
					// 从通信结构体解析DT7遥控器通道数据（来自云台板转发）
					DT7_CtrlData[now].rc.ch[0] =(int16_t)((((int16_t)(communicate->head.ctrl.befor.data.buffer[0]) | ((int16_t)(communicate->head.ctrl.befor.data.buffer[1]) << 8)) & 0x07FF) - error_ch0 - 1024);
					DT7_CtrlData[now].rc.ch[1] =(int16_t)(((((int16_t)(communicate->head.ctrl.befor.data.buffer[1]) >> 3)| ((int16_t)(communicate->head.ctrl.befor.data.buffer[2]) << 5)) & 0x07FF) - error_ch1 - 1024);
					DT7_CtrlData[now].rc.ch[2] =(int16_t)(((((int16_t)(communicate->head.ctrl.befor.data.buffer[2]) >> 6)| ((int16_t)(communicate->head.ctrl.befor.data.buffer[3]) << 2) |((int16_t)(communicate->head.ctrl.befor.data.buffer[4]) << 10)) & 0x07FF)- error_ch2 - 1024);
					DT7_CtrlData[now].rc.ch[3] =(int16_t)(((((int16_t)(communicate->head.ctrl.befor.data.buffer[4]) >> 1)| ((int16_t)(communicate->head.ctrl.befor.data.buffer[5])<<7)) & 0x07FF) - error_ch3 - 1024);
					// 应用死区处理（消除摇杆中立区误差）
					DT7_CtrlData[now].rc.ch[0] =QWF_Dead(DT7_CtrlData[now].rc.ch[0] ,10,-10);
					DT7_CtrlData[now].rc.ch[1] =QWF_Dead(DT7_CtrlData[now].rc.ch[1] ,10,-10);
					DT7_CtrlData[now].rc.ch[2] =QWF_Dead(DT7_CtrlData[now].rc.ch[2] ,10,-10);
					DT7_CtrlData[now].rc.ch[3] =QWF_Dead(DT7_CtrlData[now].rc.ch[3] ,10,-10);
					// 解析开关状态（s[0]为云台模式开关）
					DT7_CtrlData[now].rc.s[0] = (((communicate->head.ctrl.befor.data.buffer[5]) >> 4) & 0x000C) >> 2;
					DT7_CtrlData[now].rc.s[1] = (((communicate->head.ctrl.befor.data.buffer[5]) >> 4) & 0x0003);
					DT7_CtrlData[now].rc.knob=((uint16_t)communicate->head.ctrl.befor.data.buffer[6])|((uint16_t)communicate->head.ctrl.later.data.buffer[0]<<8)-1024;
				}break;
			}
		}break;
		case (KM):{
			switch((int)ctrl->type){
				case(VT13):{
					VT13_CtrlData[now].mouse.x = (communicate->head.ctrl.befor.data.buffer[10-10] | (communicate->head.ctrl.befor.data.buffer[11-10] << 8));
					VT13_CtrlData[now].mouse.y = (communicate->head.ctrl.befor.data.buffer[12-10] | (communicate->head.ctrl.befor.data.buffer[13-10] << 8));
					VT13_CtrlData[now].mouse.z = (communicate->head.ctrl.befor.data.buffer[14-10] | (communicate->head.ctrl.befor.data.buffer[15-10] << 8));
					
					VT13_CtrlData[now].mouse.press_l = (communicate->head.ctrl.befor.data.buffer[16-10] >> 0) & 0x03;
					VT13_CtrlData[now].mouse.press_r = (communicate->head.ctrl.befor.data.buffer[16-10] >> 2) & 0x03;
					VT13_CtrlData[now].mouse.middle  = (communicate->head.ctrl.befor.data.buffer[16-10] >> 4) & 0x03;
					
					*(int16_t*)(&VT13_CtrlData[now].key) = (communicate->head.ctrl.later.data.buffer[17-17] | (communicate->head.ctrl.later.data.buffer[18-17] << 8));
				}break;
				case (DT7):{	
					DT7_CtrlData[last]=DT7_CtrlData[now];
					DT7_CtrlData[now].mouse.x 		= ((int16_t)communicate->head.ctrl.befor.data.buffer[0]) 				  | ((int16_t)communicate->head.ctrl.befor.data.buffer[1] << 8);
					DT7_CtrlData[now].mouse.y 		= ((int16_t)communicate->head.ctrl.befor.data.buffer[2]) 				  | ((int16_t)communicate->head.ctrl.befor.data.buffer[3] << 8);
					DT7_CtrlData[now].mouse.z 		= ((int16_t)communicate->head.ctrl.befor.data.buffer[4]) 				  | ((int16_t)communicate->head.ctrl.befor.data.buffer[5] << 8);
					DT7_CtrlData[now].mouse.press_l	= communicate->head.ctrl.later.data.buffer[6];
					DT7_CtrlData[now].mouse.press_r = communicate->head.ctrl.later.data.buffer[0];
					*(int16_t*)(&ctrl->KM[now].key) = ((int16_t)communicate->head.ctrl.later.data.buffer[1])| ((int16_t)communicate->head.ctrl.later.data.buffer[2] << 8);
				}break;
			}
		}break;
	}	
	QWF_Ctrl_Func();

}
#endif
